home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1994 DJ Delorie. Donated to the public domain.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- ╔═══════════════════════════════════════════════════════════════════════╗
- ║ Far Pointer Simulation Functions ║
- ╚═══════════════════════════════════════════════════════════════════════╝
-
- This file attempts to make up for the lack of a "far" keyword in GCC.
- Although it doesn't provide access to far call APIs (like Windows), it
- does allow you to do far pointer data access without the overhead of
- movedata() or dosmemget/dosmemput().
-
- You should *always* include this file when using these functions and
- compile with optimization enabled. They don't exist as normal functions
- in any library, and they compile down to only a few opcodes when used
- this way. They are almost as fast as native pointer operations, and
- about as fast as far pointers can get.
-
- If you don't use optimization, this file becomes prototypes for
- farptr.c, which generates real functions for these when not optimizing.
- When optimizing, farptr.c compiles to nothing.
-
- There are two types of functions here - standalone and invariant. The
- standalone functions take a selector and offset. These are used when
- you need only a few accesses, time isn't critical, or you don't know
- what's in the %fs register. The invariant ones don't take a selector,
- they only take an offset. These are used inside loops and in
- time-critical accesses where the selector doesn't change. To specify
- the selector, use the farsetsel() function. That selector is used for
- all farns*() functions until changed.
-
- The farpoke* and farpeek* take selectors.
-
- The farnspoke* and farnspeek* don't (note the `ns' for `no selector').
-
- Warning: These routines all use the %fs register for their accesses.
- GCC normally uses only %ds and %es, and libc functions (movedata,
- dosmemget, dosmemput) use %gs. Still, you should be careful about
- assumptions concerning whether or not the value you put in %fs will be
- preserved across calls to other functions. If you guess wrong, your
- program will crash. Better safe than sorry.
-
- Note: There are two places where asm constraints are casted. One
- (farpokeb) is because signed char won't fit in unsigned char's range
- when arguments are constants, the other (farpeekb) gets compiled to (for
- example) %eax, but gas puts in opcodes for (for example) %al instead.
- Both are workarounds for errors that gcc emits (but I don't know why).
-
- */
-
- #ifndef _FAR_POINTER_H_
- #define _FAR_POINTER_H_
-
- extern inline void
- _farpokeb(unsigned short selector,
- unsigned long offset,
- unsigned char value)
- {
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movb %0,(%1)"
- :
- : "r" ((unsigned char)value), "r" (offset));
- }
-
- extern inline void
- _farpokew(unsigned short selector,
- unsigned long offset,
- unsigned short value)
- {
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movw %0,(%1)"
- :
- : "r" (value), "r" (offset));
- }
-
- extern inline void
- _farpokel(unsigned short selector,
- unsigned long offset,
- unsigned long value)
- {
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movl %0,(%1)"
- :
- : "r" (value), "r" (offset));
- }
-
- extern inline unsigned char
- _farpeekb(unsigned short selector,
- unsigned long offset)
- {
- unsigned char result;
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movb (%1),%0"
- : "=r" ((int)result)
- : "r" (offset));
- return result;
- }
-
- extern inline unsigned short
- _farpeekw(unsigned short selector,
- unsigned long offset)
- {
- unsigned short result;
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movw (%1),%0"
- : "=r" (result)
- : "r" (offset));
- return result;
- }
-
- extern inline unsigned long
- _farpeekl(unsigned short selector,
- unsigned long offset)
- {
- unsigned long result;
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- asm(".byte 0x64\n"
- " movl (%1),%0"
- : "=r" (result)
- : "r" (offset));
- return result;
- }
-
- extern inline void
- _farsetsel(unsigned short selector)
- {
- asm("movw %0,%%fs"
- :
- : "r" (selector));
- }
-
- extern inline unsigned char
- _farnspokeb(unsigned long offset,
- unsigned char value)
- {
- asm(".byte 0x64\n"
- " movb %0,(%1)"
- :
- : "r" (value), "r" (offset));
- }
-
- extern inline unsigned char
- _farnspokew(unsigned long offset,
- unsigned short value)
- {
- asm(".byte 0x64\n"
- " movw %0,(%1)"
- :
- : "r" (value), "r" (offset));
- }
-
- extern inline unsigned char
- _farnspokel(unsigned long offset,
- unsigned long value)
- {
- asm(".byte 0x64\n"
- " movl %0,(%1)"
- :
- : "r" (value), "r" (offset));
- }
-
- extern inline unsigned char
- _farnspeekb(unsigned long offset)
- {
- unsigned char result;
- asm(".byte 0x64\n"
- " movb (%1),%0"
- : "=r" (result)
- : "r" (offset));
- return result;
- }
-
- extern inline unsigned short
- _farnspeekw(unsigned long offset)
- {
- unsigned short result;
- asm(".byte 0x64\n"
- " movw (%1),%0"
- : "=r" (result)
- : "r" (offset));
- return result;
- }
-
- extern inline unsigned long
- _farnspeekl(unsigned long offset)
- {
- unsigned long result;
- asm(".byte 0x64\n"
- " movl (%1),%0"
- : "=r" (result)
- : "r" (offset));
- return result;
- }
-
- #endif /* _FAR_POINTER_H_ */
-
-